// Game
(function( $ ){
	// default ship lengths
	var totalShips = 10, self = null;
	//ship lengths are max up to 10 atm
	var ships = [4, 3, 3, 2, 2, 2, 1, 1, 1, 1];
	var shipUsed = [], myTurn = false;
	var gameStarted = false, shipsPlaced = 0;
	var gameStatus = 0; //1 - win, 2 - loss
	
	
	/* --- GAME LOGIC --- */
  function BattleShips( selector, columnCount, rowCount ) {
    this.selector = selector;
    this.columnCount = Math.min(columnCount, 24);
    this.rowCount = Math.min(rowCount, 24);
    this.reset();
    self = this;
    //redirect mouse events for table - user input    
   }
   
   BattleShips.prototype.reset = function() {
    //make the tables
    buildFields();
    //Classes for both fields
    this.myField = new Table('#mina', this.rowCount, this.columnCount, false);
    this.oppField = new Table('#vastane', this.rowCount, this.columnCount, true);
    //Genereerime vastasele suvalise välja!
    //this.oppField.generateField(totalShips, ships);
    this.mouseHorizontal = true;
    var selfa = this;
    $("#vastane").on("mousedown", "td.field", function(e) {
      selfa.handleMouseOppField(e); //siin skoobis on teine *this*
    });
    $("#mina").on("mouseover mouseleave mousedown", "td.field", function(e) {
      selfa.handleMouseMyField(e); //siin skoobis on teine *this*
    }); 
    shipsPlaced = 0;
    gameStarted = false;
    shipUsed = [];
    for (var i = 0; i < totalShips; i++) {
      shipUsed.push(false);
    }
    this.history = {"moves":[]};
  };
  
  BattleShips.prototype.startGame = function() {
    if (gameStarted) return;
    gameStarted = true;
    turn = false;
    
    data = {"action" : "place",
            "placement" : this.myField.tableEncode()};
    
    this.history["myPlacement"] = data["placement"];
    
    $.post("BattleServlet", data, function(resp) {
      var t = resp.split("&");
      console.log("startGame: "+resp);
      self.history["myname"] = t[2];
      self.history["oppname"] = t[1];
      playSound("battlestart.ogg");
      myTurn = t[0] == "start";
      self.history["starter"] = myTurn;
      if (!myTurn) {
        console.log("S: Waiting for opponents move");
        $.post("BattleServlet", {"action":"waitMove"}, self.oppMove);
      }
    });
  };
  
  BattleShips.prototype.makeMove = function(x, y) {
    if (this.oppField.isBombed(x, y) || !myTurn) return;
    data = {"action": "bomb", "x":x, "y":y};
    $.post("BattleServlet", data, function(resp) {
      self.history["moves"].push([x, y]);
      // types: "hit", "miss", "hit;hlxy" [h - horizontal(1,0), l - length, x,y - positions of start
      console.log("MakeMove: "+resp);
      var t = resp.split(";");
      myTurn = t[0] == "hit";
      self.oppField.placeBomb(x, y, myTurn);
      if (t.length >= 2) {
        var hor = t[1][0] == '1';
        var l = parseInt(t[1][1]);
        x = parseInt(t[1][2]);
        y = parseInt(t[1][3]);
        console.log("adding: "+x+y+l+hor);
        self.oppField.addShip(x, y, l, hor);
      }
      if (t.length == 3) {
        self.history["opponentPlacement"] = t[2];
        gameStatus = 1; //won
        toLocalStorage(self.history);
        $("#mangusonum").statusPopup();
        console.log(self.history);
      }
      
      //missed, wait for opponent
      if (!myTurn) {
        console.log("Waiting for opponents move");
        $.post("BattleServlet", {"action":"waitMove"}, self.oppMove);
      }
    });
  };
	
  //Opponent made a move
  BattleShips.prototype.oppMove = function(resp) {
    console.log("Opponent made move: " + resp);
    //First 2 - xy coordinates of opponent move
    var x = parseInt(resp[0]);
    var y = parseInt(resp[1]);
    self.history["moves"].push([x, y]);
    //opponent hit
    if (self.myField.bomb(x, y, true)) {
      //lost.
      var t = resp.split(";");
      if (t.length == 2) {
        self.history["opponentPlacement"] = t[1];
        gameStatus = 2; //lost
        console.log(self.history);
        toLocalStorage(self.history);
        $("#mangusonum").statusPopup();
        return;
      }
      console.log("Waiting for opponents next move");
      $.post("BattleServlet", {"action":"waitMove"}, self.oppMove);
    }
    else {
      console.log("My turn");
      myTurn = true;
    }
  };
  
  function buildFields() {
    $("#secondTableDiv").html(gamefieldHTML("mina"));
    $("#firstTableDiv").html(gamefieldHTML("vastane"));
  };
  
  function gamefieldHTML(id) {
    //produces a table with the id as identifier for the game
    var result = [];
    result.push('<table class="manguvali" id="' + id + '">');
    //table body
    for (var i = 0; i < 10; i++) {
      result.push("<tr>");
      for (var j = 0; j < 10; j++)
        result.push('<td class="field"></td>');
      result.push("</tr>");
    }
    result.push('</table>');
    return result.join('\n');
  }
	
	//Handle mouse on my field!
	BattleShips.prototype.handleMouseMyField = function(event) {
    //mouseover - mouse is over the cell
    //mouseleave - mouse left the cell
    //mousedown - mouse click. 
    //  event.which tells you which key was used:
    //    1 - left, 2 - middle, 3 - right 
    var leftClick = (event.which == 1);
    var target = $(event.target);

    var x = target.getRow();
    var y = target.getCol();	
    //Saab laevu paigutada? no teeme siis seda!
    var fst = null;
    if (shipsPlaced < totalShips)
      fst = firstFalse(shipUsed, totalShips); //get first ship that needs to be placed
    
    if (event.type == "mouseover" && shipsPlaced < totalShips && !gameStarted) {
      if (this.myField.canPlace(x, y, ships[fst], this.mouseHorizontal)) {
        this.myField.addShadow(x, y, ships[fst], this.mouseHorizontal);
      }
    }  
    else if (event.type == "mouseleave") {
      this.myField.removeShadow();
    }
    else if (event.type == "mousedown" && !gameStarted) {
        if (!leftClick) {
          this.mouseHorizontal = !this.mouseHorizontal;
          this.myField.removeShadow();
          if (shipsPlaced < totalShips && this.myField.canPlace(x, y, ships[fst], this.mouseHorizontal)) {
            this.myField.addShadow(x, y, ships[fst], this.mouseHorizontal);
          }          
        }
        else if (shipsPlaced < totalShips && this.myField.canPlace(x, y, ships[fst], this.mouseHorizontal)) {
          this.myField.addShip(x, y, ships[fst], this.mouseHorizontal);
          shipUsed[fst] = true;
          shipsPlaced++;
        }
        else {
          //laevade ümber paigutamine
          var type = this.myField.getShipType(x, y);
          if (type === null) return; //ei olnudki laev
          var length = parseInt(type[1]), sx = x, sy = y;
          //leiame selle laeva, märgime et ei ole kasutuses
          var indx = find(length, ships, totalShips);
          shipUsed[indx] = false;
          shipsPlaced--;
          //kuvame hiire all
          this.mouseHorizontal = 'h' == type[0];
          if (this.mouseHorizontal) {sy -= parseInt(type[2])-1;}
          else {sx -= parseInt(type[2])-1;}
          this.myField.removeShip(sx, sy,length, this.mouseHorizontal);
          if (this.myField.canPlace(x, y, ships[indx], this.mouseHorizontal))
            this.myField.addShadow(x, y, ships[indx], this.mouseHorizontal);
        }
    }
	};
	BattleShips.prototype.handleMouseOppField = function(event) {
    //mouseover - mouse is over the cell
    //mouseleave - mouse left the cell
    //mousedown - mouse click. 
    //  event.which tells you which key was used:
    //    1 - left, 2 - middle, 3 - right	
    var target = $(event.target);
    var x = target.getRow();
    var y = target.getCol();
    if (event.which == 1 && gameStarted && myTurn && !this.oppField.isBombed(x, y)) {
      this.makeMove(x, y);
//      if (!this.oppField.bomb(x, y, true)) {
        //turn = !turn;
//        while (this.randomBomb()) {}
//      }
      //handle game end. TODO: move elsewhere
//      status = this.status();
//      if (status == BattleShips.statusCode.won || status == BattleShips.statusCode.lost)
//        $("#mangusonum").statusPopup();
    }
	};
	
	
	BattleShips.prototype.status = function() {
	  if (shipsPlaced < totalShips) {
	    return BattleShips.statusCode.notEnoughShips;
	 }
	  if (gameStarted) {
	    if (gameStatus == 1)
	      return BattleShips.statusCode.won;
	    else if (gameStatus == 2)
	      return BattleShips.statusCode.lost;
	    return BattleShips.statusCode.started;
	  }
	  else
	   return BattleShips.statusCode.enoughShips;
	};
	
	BattleShips.prototype.randomBomb = function() {
	  var x, y;
	  while (true) {
	    x = Math.floor(Math.random() * totalShips);
	    y = Math.floor(Math.random() * totalShips);
	    if (!this.myField.isBombed(x, y)) {
	      return this.myField.bomb(x, y, false);
	    }
	  }
	};
	
	function toLocalStorage(history) {
	  gamesCount = localStorage["gamesCount"];
	  if (gamesCount === null || gamesCount == "null")
	    gamesCount = 0;
	  else
	    gamesCount = parseInt(gamesCount);
	  localStorage["game" + gamesCount] = JSON.stringify(history);
	  localStorage["gamesCount"] = gamesCount + 1;
	}
	
	window.BattleShips = BattleShips;
	window.buildFields = buildFields;
	window.gamefieldHTML = gamefieldHTML;
	
	BattleShips.statusCode = {
	  notEnoughShips: 0,
	  enoughShips: 1,
	  started: 2,
	  lost: 3,
	  won: 4,
	  playbackEnded: 5
	};
})( jQuery );

//Playback
(function( $ ){
  var m_history = [], moves = [];
  var at = 0,  turn = 0;
  var m_delay = 5000;
  
  function playback(history, delay) {
    buildFields();
    console.log(history);
    m_history = history;
    moves = history["moves"];
    turn = history["starter"] ? 1 : 0;
    m_delay = delay;
    this.field = [];
    this.field.push(new Table('#mina', this.rowCount, this.columnCount));
    this.field[0].setEncoding(m_history["myPlacement"]);
    this.field.push(new Table('#vastane', this.rowCount, this.columnCount));
    this.field[1].setEncoding(m_history["opponentPlacement"]);
    // Some kind of reset needed.
    at = 0;
    nextMove(this);
  }
  
  function nextMove(self) {
    // self.myField.bomb(x, y, true)
    
    if (at >= moves.length) {
      console.log("PLAYBACK OVER");
      setTimeout(function() {$("#mangusonum").statusPopup();}, 3 * m_delay);
      return;
    }
    
    // console.log(moves);
    var x = moves[at][0], y = moves[at][1];
    console.log("Move " + at + "/" + (moves.length-1) + " by " + turn + " to " + x + "," + y);
    if (!self.field[turn].bomb(x, y, true))
      turn = 1 - turn;
    at += 1;
    setTimeout(nextMove, m_delay, self);
  };
  
  window.playback = playback;
})( jQuery );